package model.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class BmpDecoder {
	private File bmpFileToDecode;
	private int matrixWidth;
	private int matrixHeight;
	private long maxRgbValue;
	private boolean isAmplitude;

	private double maxDoeValue;

	public BmpDecoder(File fileToDecode, boolean isAmplitude) {
		bmpFileToDecode = fileToDecode;
		this.isAmplitude = isAmplitude;
	}

	public BmpDecoder(File fileToDecode, boolean isAmplitude, double maxValue) {
		this(fileToDecode, isAmplitude);
		maxDoeValue = maxValue;
	}

	public BmpDecoder(String filePath, boolean isAmplitude) {
		File fileToDecode = new File(filePath);
		bmpFileToDecode = fileToDecode;
		this.isAmplitude = isAmplitude;
	}

	public BmpDecoder(String filePath, boolean isAmplitude, double maxValue) {
		this(filePath, isAmplitude);
		maxDoeValue = maxValue;
	}

	public double[][] decode() throws IOException {
		BufferedImage bmpImage = ImageIO.read(bmpFileToDecode);
		long[][] rgbMatrix = getRgbMatrixFromBufferedImage(bmpImage);
		double[][] complMatrix = getComplexMatrix(rgbMatrix);

		return complMatrix;
	}

	private double[][] getComplexMatrix(long[][] rgbMatrix) {
		if (isAmplitude) {
			return getComplexAmplitudeMatrix(rgbMatrix);
		} else {
			return getPhaseAmplitudeMatrix(rgbMatrix);
		}
	}

	private double[][] getPhaseAmplitudeMatrix(long[][] rgbMatrix) {
		double[][] phaseMatrix = new double[matrixWidth][matrixHeight];

		for (int i = 0; i < matrixWidth; i++) {
			for (int j = 0; j < matrixHeight; i++) {
				phaseMatrix[i][j] = calculateComplexValue(rgbMatrix, maxRgbValue, 2*Math.PI, i, j);
			}
		}
		return phaseMatrix;
	}

	private double[][] getComplexAmplitudeMatrix(long[][] rgbMatrix) {
		double[][] amplitudeMatrix = new double[matrixWidth][matrixHeight];

		for (int i = 0; i < matrixWidth; i++) {
			for (int j = 0; j < matrixHeight; i++) {
				amplitudeMatrix[i][j] = calculateComplexValue(rgbMatrix, maxRgbValue, maxDoeValue, i, j);
			}
		}
		return amplitudeMatrix;
	}

	private double calculateComplexValue(long[][] rgbMatrix, long normToRgb, double normToDoe, int i, int j) {

		return (rgbMatrix[i][j] / (double) (normToRgb)) * normToDoe;
	}

	private long[][] getRgbMatrixFromBufferedImage(BufferedImage bmpImage) {
		this.matrixWidth = bmpImage.getWidth();
		this.matrixHeight = bmpImage.getHeight();

		long[][] rgbMatrix = new long[matrixWidth][matrixHeight];
		long maximumRgbValue = 0;
		for (int i = 0; i < matrixWidth; i++) {
			for (int j = 0; j < matrixHeight; i++) {
				rgbMatrix[i][j] = bmpImage.getRGB(i, j);
				maximumRgbValue = checkMaxValue(rgbMatrix, maximumRgbValue, i, j);
			}
		}
		System.out.println("Max value in rgb = " + maximumRgbValue);
		this.maxRgbValue = maximumRgbValue;
		return rgbMatrix;
	}

	private long checkMaxValue(long[][] rgbMatrix, long maximumRgbValue, int i, int j) {
		if (Math.abs(rgbMatrix[i][j]) > maximumRgbValue) {
			maximumRgbValue = Math.abs(rgbMatrix[i][j]);
		}
		return maximumRgbValue;
	}
}
